Speech @Whymca '11
Tiyla is an infrastructure that enables management of software internationalization.
- Multiplatform Libraries
- Public Api
- Support for multiple translation Crews
- Support for Crowdsourcing
- Community database of translations
.. and more :]
4. About Us
Chi
siamo
Dal 1998 sviluppiamo so/ware per ges4one da4 su interfaccia Web
Nel 2004 realizzata prima versione piaAaforma RAD e BPM -‐
Dal 2009 introdoAa estensione Mobile Mul4piaAaforma
( , , , , )
Reparto R&D con 20 dipenden4 tecnici (job@apparound.com)
Il
Prodo.o
e
le
Soluzioni
AAraverso gli strumen4 RAD e BPM offer4 dalla nostra piaAaforma
possiamo realizzare velocemente applicazioni Mobile Mul4piaAaforma in
grado di ges4re, da4, contenu4 e processi
Chi
ha
scelto
al
nostra
tecnologia
4
6. Intro: Roundup
Internazionalizzazione del
software oggi
Interazione Software / Utente
La soluzione Tiyla: Goals &
Examples
6
7. Software & i18n
Problematica non nuova ma attualissima
Internazionalizzazione
“Progettazione per mercati diversi da quello di origine in cui
si sviluppa”
Localizzazione
“Le azioni volte a rendere il software fruibile per tali mercati”
7
8. Why i18n is a chance
11 persone su 12 nel mondo non conoscono
l’Inglese
Psicologicamente rassicurante
pagare per un’App da poter usare nella
propria lingua
Affinità culturali trasversali alle lingue
Raggiungere nuovi mercati / paesi non in crisi
8
9. Markets For All
Markets Mobile & Desktop
Multi-language and Multi Country
Billing Support
9
10. With great opportunities... few problems
Sviluppo
• Supporto nativo i18n diverso per ogni
dispositivo
• Gestione “script automatici” traduzioni
attraverso un sw specifico: integrazione?
• Distribuzione delle traduzioni in diversi formati
(crossplatform)
10
11. With great opportunities... few problems
Gestione
• A chi rivolgersi per le traduzioni
• Come gestire le collaborazioni
• Come gestire la validazione della traduzione
• Tenere sotto controllo il processo per più
lingue e più fornitori
11
12. With great opportunities... few problems
Pubblicazione
• Ri-Pubblicazione dell’applicativo quando è
disponibile una nuova lingua
• Diversi store / versioni
• Tempi di attesa
• Possibilità di reject (per qualsiasi fantasioso
motivo)
12
13. Our Solution: Tiyla
Crossplatform Crowdsourcing
Libraries Collaboration
Api Process Control
13
14. Tiyla Components
Database AS Crossplatform
• Community Api Libs
• Applicazione API Gui Libs
• Crowdsourcing Admin Manager
14
16. 3 core of Tiyla solution
Trasparenza
Flessibilità
Crowdsourcing
16
17. Tiyla & Trasparenza
Esigenza di Traduzioni “Trasparenti”
con Tiyla nel Backend
(es Software Enterprise)
• Supporto alla crew di traduzione aziendale o ai
Partner in outsourcing tramite Tiyla
• Offerta traduzioni Tiyla Crew dai nostri partner
• Disponibilità delle traduzioni di default “Community”
• Generazione dei file per i18n multipiattaforma da
includere offline
17
18. Tiyla & Trasparenza
Le traduzioni sono generate all’atto della
compilazione del progetto.
Plugin Ambiente Tiyla Desktop
di sviluppo
• Il sistema Tiyla è completamente nascosto all’utente
finale
• L’azienda rimane proprietaria delle proprie traduzioni
seguendone workflow & deploy
18
23. Tiyla & Trasparenza
Workflow “Standard”
• File i18n generato
da Plugin in IDE
• File i18n generato
• Registrazione App • Traduzione da Desktop Client
• Abilitazione Crew • Da Partner da includere al
• Da Community progeOo
• Da Tiyla Crew
SELL
• Build
23
24. Tiyla & Flessibilità
Si abilita l’update dell’i18n App Remoto
• Inclusione di un set base di lingue
• Update remoto (via Api) di nuove lingue per l’app
quando queste vengono validate
• Possibilità di contribuire / usufruire del db
Community delle traduzioni
24
25. Tiyla & Flessibilità
Vantaggi: Tempo = Denaro
• Possibilità di pubblicare l’applicazione partendo da
una lingua base (abbattere i tempi di debutto sul
mercato)
• Arricchire l’app “on the fly” senza bisogno di
ripubblicarla
• Correggere le traduzioni al volo
25
26. Tiyla & Flessibilità
Workflow Tiyla On The FLy
• File i18n generato
da Plugin in IDE
• Registrazione App • File i18n generato
• Abilitazione Crew da Desktop Client
da includere al
progeOo
• Build
• Traduzione
• Da Partner
• Da Commuinity
• Da Tiyla Crew
• Correzioni
26
• Nuove Lingue SELL
30. Tiyla & Crowdsourcing
Infrastruttura:
• Gestione di base Utenti
• Traduzione degli utenti a partire da una lingua E
LU
certificata E VA
LU
• Rating delle traduzioni
VA
• Conteggio attività dell’utente in Crowd Tiyla
– Rating degli utenti (individuare best & worst) E
LU
– Possibilità di indire contest
VA
30
37. iOS + MacOS: Supporto Nativo
• Prevede un file “Localizzato” aggiunto al bundle del
progetto
• Automatico in base alla lingua impostata nel
dispositivo
• API da utilizzare
• Traduce anche i contenuti XIB Disegnati usando il
Designer
37
41. iOS + MacOS: Supporto Nativo
• Richiede la ricompilazione: File (*) da mettere nel
bundle
• Aggiungere un file per ogni nuova lingua da tradurre
• Modificare tutti i file se cambia la lingua del
“programmatore”
41
42. Tiyla & iOS: .h
//! Profile management
//! create new profile, or if exist and password match return TRUE
-(BOOL)registerProfile:(NSString *)email password:(NSString *)password;
//! verify your password
-(BOOL)loginProfile:(NSString *)email password:(NSString *)password;
//! remove profile
-(BOOL)dropProfile:(NSString *)email password:(NSString *)password;
//! return data for profile, if password is empty you will receive public informations
-(NSDictionary *)getProfile:(NSString *)email password:(NSString *)password;
//! Developer API:
//! create new Application, if application exists does do nothing
-(NSString *)registerApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password;
//! set KeyPairs App info to db
-(BOOL)setApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password data:(NSDictionary *)data;
//! Crew manage
-(BOOL)linkCrew:(NSString *)emailCrew toApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)
password;
-(BOOL)unlinkCrew:(NSString *)emailCrew toApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)
password;
//! Translations Update Crew
-(BOOL)setTApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password language:(NSString *)
language data:(NSDictionary *)data;
//! Translations Update Developer
-(BOOL)setTRankApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password language:(NSString *)
language data:(NSDictionary *)data;
//! Translations Client
-(NSDictionary *)getApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password data:(NSDictionary
*)data;
//! get Translation * work with shots *
-(NSDictionary *)getTApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password language:
(NSString *)language data:(NSDictionary *)data;
42
45. Tiyla: Server IO GZIP
<?php
// Imposto il Xpo di ritorno
header ("content-‐type: applicaXon/json");
// Imposto il fuso orario (il server è in USA)
date_default_Xmezone_set('UTC');
// DEBUG: Memorizzo l'ora di partenza per calcolare il "peso" in fondo
$start_Xme=microXme(TRUE);
// ATTENZIONE: lo stream in ingresso POST deve essere compresso
$fp=gzopen("php://input","r");
// POST: leggo in input tuOo il JSON inviato dai client
$data = gzread($fp,1024000); // 1MB in upload (decompresso...)
// chiudo il descriOore
fclose($fp);
$fp=0;
// genero un array associaXvo dal POST
$data=json_decode($data,true);
?>
45
54. Android: Supporto Nativo
• Sistema di localizzazione integrato basato su file xml,
presenti in diverse folder con suffisso differente a seconda
della lingua (values, values-it, values-fr)
• Il file chiamato strings.xml è semplicemente un elenco di
righe chiave – valore dove il valore è appunto la stringa
tradotta.
• Da codice per recuperare la stringa corrente getString
(R.string.key)
• Se si vuole modificare o aggiungere una nuova lingua
bisogna ricompilare il programma producendo il nuovo apk
e pubblicare l’aggiornamento sul market
54
56. Tiyla & Android: API
//! Profile management
//! create new profile, or if exist and password match return TRUE
sta7c
public
boolean
registerProfile(String
email,
String
password)
//! verify your password
sta7c
public
boolean
loginProfile(String
email,
String
password)
//! remove profile
sta7c
public
boolean
dropProfile(String
email,
String
password)
//! return data for profile, if password is empty you will receive public informaXons
sta7c
public
JSONObject
getProfile(String
email,
String
password)
//! Developer API:
//! create new ApplicaXon, if applicaXon exists does do nothing
sta7c
public
String
registerApp(String
bundleId,
String
email,
String
password)
//! set KeyPairs App info to db
sta7c
public
boolean
setApp(String
bundleId,
String
email,
String
password,
JSONObject
data)
//! Crew manage
sta7c
public
boolean
linkCrew(String
emailCrew,
String
bundleId,
String
email,
String
password)
sta7c
public
boolean
unlinkCrew(String
emailCrew,
String
bundleId,
String
email,
String
password)
//! TranslaXons Update Crew
sta7c
public
boolean
setTApp(String
bundleId,
String
email,
String
password,
String
language,
JSONObject
data)
//! TranslaXons Update Developer
sta7c
public
boolean
setTRankApp(String
bundleId,
String
email,
String
password,
String
language,
JSONObject
data)
//! TranslaXons Client
sta7c
public
JSONObject
getApp(String
bundleId,
String
email,
String
password,
JSONObject
data)
//! get TranslaXon * work with shots *
sta7c
public
JSONObject
getTApp(String
bundleId,
String
email,
String
password,
String
language,
JSONObject
data);
56
57. Tiyla & Android: RAPI
//Inizialmente comprimo i daX in formato gzip uXlizzando //Ricevo i daX dal server
//l'oggeOo GZIPOutputStream InputStream input = connecXon.getInputStream();
byte[]
compressedData
=
Library.compressData String contentEncoding = connecXon.getContentEncoding
(dataS.getBytes()); ();
BufferedInputStream inputB = new
BufferedInputStream
//-‐-‐-‐
(input,
10000);
//Apro una HOpURLConnecXon verso il server
connecXon = (HOpURLConnecXon) new
URL //-‐-‐-‐
(url).openConnec8on(); while
((nRead
=
inputB.read(data,
0,
data.length))
!=
-‐1)
//-‐-‐ {
//Imposto il parametro "Accept-‐Encoding" "deflate" per byteAOSB.write(data, 0, nRead);
ricevere i daX in formato compresso }
connecXon.addRequestProperty("Accept-‐Encoding", "deflate");
connecXon.setRequestProperty("Content-‐Type","applicaXon/ //-‐-‐
json"); //ScompaOo i daX dal server
received_result = new
String(Library.decompressData
//Invio i daX
(received_result.getBytes()));
connecXon.getOutputStream().write(compressedData); //-‐-‐
57
61. Windows & WP7:
Supporto Nativo
• Sistema di localizzazione integrato basato su file di risorse (resx),
con nomi organizzati gerarchicamente a partire dal file della lingua
di default. Ad esempio myRes.resx contiene le informazioni in lingua
di default, mentre una eventuale traduzione in francese standard si
ottiene aggiungendo il file myRes.fr.resx al progetto
• Un file di risorse è composto da una serie di coppie chiave-valore.
Tutti i file dovrebbero avere le stesse chiavi a cui corrispondono le
versioni in lingua degli stessi testi
• Le interfacce utente invocano le stringhe contenute nei file di risorse
tramite la loro chiave, usando l’operatore binding
• Se si vuole modificare o aggiungere una nuova lingua bisogna
ricompilare il programma producendo il nuovo xap e pubblicare
l’aggiornamento sul market
61
63. Windows & WP7: Supporto
Nativo
• Le chiamate al server in WP7 sono gestite in
modo asincrono.
• La libreria mette a disposizione una serie di
eventi che vengono generati quando la chiamata
è stata completata.
63
64. Tiyla & WP7: Metodi (1/3)
public
delegate
void
OperationCompletedDelegate
(String
result,
Exception
error);
public
event
OperationCompletedDelegate
OperationCompleted;
///
<summary>
///
Profile
management
///
create
new
profile,
or
if
exist
and
password
match
return
TRUE
///
</summary>
public
void
registerProfile(String
email,
String
password);
public
OperationCompletedDelegate
registerProfile_Completed;
///
<summary>
///
verify
your
password
///
</summary>
public
void
loginProfile(String
email,
String
password);
public
OperationCompletedDelegate
loginProfile_Completed;
///
<summary>
///
remove
profile
///
</summary>
public
void
dropProfile(String
email,
String
password);
public
OperationCompletedDelegate
dropProfile_Completed;
///
<summary>
///
return
data
for
profile,
if
password
is
empty
you
will
receive
informations
///
</summary>
public
void
getProfileString(String
email,
String
password);
public
OperationCompletedDelegate
getProfileString_Completed;
///
<summary>
///
create
new
Application,
if
application
exists
does
do
nothing
///
</summary>
public
void
registerApp(String
bundleId,
String
email,
String
password);
public
OperationCompletedDelegate
registerApp_Completed;
64
65. Tiyla & WP7: Metodi (2/3)
///
<summary>
///
set
KeyPairs
App
info
to
db
///
</summary>
public
void
setApp(String
bundleId,
String
email,
String
password,
Dictionary<string,
string>
data);
public
OperationCompletedDelegate
setApp_Completed;
///
<summary>
///
Crew
manage
///
</summary>
public
void
linkCrew(String
emailCrew,
String
bundleId,
String
email,
String
password);
public
OperationCompletedDelegate
linkCrew_Completed;
///
<summary>
///
Crew
manage
///
</summary>
public
void
unlinkCrew(String
emailCrew,
String
bundleId,
String
email,
String
password);
public
OperationCompletedDelegate
unlinkCrew_Completed;
///
<summary>
///
Translations
Update
Crew
///
</summary>
public
void
setTApp(String
bundleId,
String
email,
String
password,
String
language,
Dictionary<string,
string>
data);
public
OperationCompletedDelegate
setTApp_Completed;
///
<summary>
///
Translations
Update
Developer
///
</summary>
public
bool
setTRankApp(String
bundleId,
String
email,
String
password,
String
language,
Dictionary<string,
string>
data);
public
OperationCompletedDelegate
setTRankApp_Completed;
///
<summary>
///
Translations
Client
///
</summary>
public
void
getApp(String
bundleId,
String
email,
String
password,
Dictionary<string,
string>
data);
public
OperationCompletedDelegate
getApp_Completed;
65
66. Tiyla & WP7: Metodi (3/3)
///
<summary>
///
get
Translation
*
work
with
shots
*
///
</summary>
public
void
getTApp(String
bundleId,
String
email,
String
password,
String
language,
Dictionary<string,
string>
data);
public
OperationCompletedDelegate
getTApp_Completed;
///
<summary>
///
get
Translation
*
work
with
shots
*
///
</summary>
public
void
getTApp(String
bundleId,
String
email,
String
password,
String
language,
Dictionary<string,
string>
data);
public
OperationCompletedDelegate
getTApp_Completed;
66
67. Tiyla & WP7: RAPI (1/3)
• Per implementare alcune funzionalità sono
state usate librerie open source pubblicate da
CODEPLEX:
• JSON.NET -
http://json.codeplex.com/releases/view/64935
• Silverlight SharpZipLib -
http://slsharpziplib.codeplex.com/releases/view/50561
67